AVR652.c

Go to the documentation of this file.
00001 #include <avr/io.h>
00002 #include <stdlib.h>
00003 #include <util/delay.h>
00004 #include <avr/interrupt.h>
00005 #include <avr/eeprom.h>
00006 
00007 // CONSTANTS
00008  
00009 #define KEY_A     0x10              // switch on PB4
00010 #define KEY_B     0x20              // switch on PB5
00011 #define KEY_MODE  0x04              // swithc on PB2
00012 
00013 #define TRUE      1
00014 #define FALSE     0
00015 
00016 #define GAUGE_MAX 0x4C
00017 #define GAUGE_MIN 0x24
00018 
00019 // GLOBAL VARIABLES
00020 
00021 unsigned char speed = 16;
00022 
00023 unsigned int EEMEM intensity[12] = {16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32};
00024 unsigned int EEMEM user_speed = 12;
00025 unsigned int EEMEM torch_status = 17;
00026 
00027 unsigned char keybuffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00028 unsigned char keybuffer_index = 0;
00029 
00030 //  index |  0  |  1  |  2  |  3 |   4  |  5  |  6  |  7  |  8  |  9  |  10 |  11
00031 //  ------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
00032 //  I/O   | PA0 | PA1 | PA2 | PA3 | PA4 | PA5 | PA6 | PB0 | PB3 | PB6 | PB7 | PB1
00033 
00034 volatile unsigned char LED[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
00035 unsigned char led_pwm = 0;
00036 
00037 
00038 //  Looks for a Valid Keypress
00039 // Note: all switches must be connected to same port
00040 
00041 unsigned char pressed(unsigned char key)
00042 {
00043 unsigned char i, sum;
00044         sum = key;
00045         for(i=0; i<8; i++)
00046         {
00047                 sum &= keybuffer[i];
00048         }
00049         if(sum > 0)
00050                 return(TRUE);
00051         else
00052                 return(FALSE);
00053 }
00054 
00055 //  LED layout:
00056 //  --------------------------
00057 //  10      09      08      07
00058 //  06  05  04  03  02  01  00
00059 //  09      10      07      08
00060 //  --------------------------
00061 //  
00062 //  eyes     |   1   |   2   |   3   |   4   |    5   |     6    |
00063 //  ---------+-------+-------+-------+-------+--------+----------+
00064 //           | .   . | .   * | .   * | *   * |  *   * |   *   *  |
00065 //  pattern  | . * . | . . . | . * . | . . . |  . * . |   * . *  |
00066 //           | .   . | *   . | *   . | *   * |  *   * |   *   *  |
00067 //  ---------+-------+-------+-------+-------+--------+----------+
00068 //  leds 1   | 1     | 7     | 1,7   | 7,8   | 1,7,8  | 0,2,7,8  |
00069 //  leds 2   | 5     | 9     | 5,9   | 9,10  | 5,9,10 | 4,6,9,10 |
00070 
00071 
00072 void  showDice(unsigned char dice, unsigned char eyes, unsigned char strength)
00073 {
00074 const unsigned int  pat[2][6] = { {0x0002, 0x0080, 0x0082, 0x0180, 0x0182, 0x0185},
00075                                     {0x0020, 0x0200, 0x0220, 0x0a00, 0x0a20, 0x0650} };
00076 unsigned int  j, m;
00077 
00078         m=pat[dice][eyes];
00079         for(j=0; j<11; j++)
00080         {
00081                 if(m & 0x01) 
00082                         LED[j] = eeprom_read_word(&intensity[j]);
00083                 else
00084                         LED[j] = 0;
00085                 m=m>>1;
00086         }
00087         LED[11]=0;
00088         _delay_us(500);
00089 }
00090 
00091 //  Do nothing -- go into Idle mode
00092 
00093 void  idle(void)
00094 
00095 {
00096 unsigned char i;
00097 
00098         for(i=0; i<12; i++)
00099                 LED[i]=eeprom_read_word(&intensity[i]);//Get stored intensity level from EEPROM
00100         _delay_us(100);
00101         for(i=0; i<12; i++)
00102                 LED[i] = 0;
00103         PRR=0x01;
00104         MCUCR |=(1<<SE);
00105         asm("SLEEP");
00106         PRR=0x00;
00107         while (!pressed(KEY_MODE))
00108         {
00109                 // wait for key to be released
00110         }
00111         _delay_us(100);
00112 }
00113 
00114 //  torch mode - Increase and Decrease intensity of High Brightness LED
00115 
00116 void  torch(void)
00117 {
00118 unsigned char strength = 17;
00119 
00120         strength =  eeprom_read_word(&torch_status); //Retrive Previous Intensity level from EEPROM
00121         
00122         while(!pressed(KEY_MODE))
00123         {
00124                 if(pressed(KEY_A))              //Increase intensity when KEY_A is pressed
00125                 {
00126                         if(strength < 32)
00127                                 strength += 1;
00128                 }
00129                 LED[11] = strength;
00130                 _delay_us(100);
00131                 
00132                 if(pressed(KEY_B))              //Decrease intensity when KEY_B is pressed
00133                 {
00134                         if (strength > 4)
00135                                 strength -= 1;
00136                 }
00137                 LED[11] = strength;
00138                 _delay_us(100);
00139         }
00140         eeprom_write_word(&torch_status,strength); //Store Intensity level in EEPROM
00141 }
00142 
00143 
00144 // Calculate the Number of LEDS to be lit for the present battery voltage level
00145 
00146 void  set_gauge(unsigned char level)
00147 {
00148 unsigned char i,tip;
00149 unsigned char rest;
00150 
00151         if(level > GAUGE_MIN)
00152         {
00153                 rest =GAUGE_MAX - level;
00154                 tip = rest /7;
00155                 for(i=0;i<=7;i++)
00156                 {
00157                         if(i < tip)
00158                                 LED[7-i] = 0;
00159                         else if(i > tip)
00160                                         LED[7-i]=eeprom_read_word(&intensity[7-i]);    
00161                 }
00162         }
00163         else 
00164                 if(level < GAUGE_MIN)
00165                 {
00166                         tip=0;
00167                         for(i=0;i<=7;i++) 
00168                                 LED[i]=0;
00169                 }
00170                 else if(level > GAUGE_MAX)
00171                         {
00172                                 for(i=0;i<=7;i++)  
00173                                         LED[i] = eeprom_read_word(&intensity[i]);       
00174                         }
00175 }
00176 
00177 //  Show battery voltage as LED bar
00178 
00179 void  battery_gauge(void)
00180 
00181 {
00182         ADMUX = 0x06;                     // read VBAT, reference to VCC
00183         ADCSRB = (1<<ADLAR);              // left-adjust result
00184         ADCSRA = (1<<ADEN) | (1<<ADSC);   // enable ADC & start single conversion
00185         
00186         while(!pressed(KEY_MODE))
00187         {
00188                 ADCSRA = (1<<ADEN) | (1<<ADSC);   // enable ADC & start single conversion
00189                 while(ADCSRA & (1<<ADSC));      
00190                 set_gauge(ADCH);
00191                 _delay_us(100);
00192         }
00193 }
00194 
00195 //  Placeholder for dice game mode
00196 
00197 void  dice_game(void)
00198 { 
00199 unsigned int five_5=0x07A2;
00200 unsigned char i=0;
00201 
00202         for(i=0;i<11;i++)
00203         {
00204                 if(five_5 &0x01)  
00205                         LED[i]=eeprom_read_word(&intensity[i]);
00206                 else
00207                         LED[i]=0;
00208                 five_5=five_5>>1;
00209         }
00210         _delay_us(10);
00211 
00212         while(!pressed(KEY_MODE))
00213         {
00214                 if(pressed(KEY_A))
00215                 {
00216                         showDice(1, (rand() % 6),32);
00217                 }
00218                 else if(pressed(KEY_B))
00219                          {
00220                                 showDice(0,(rand() % 6),32);
00221                          }
00222                 i++;
00223                 if(i>7) i=0;
00224                 _delay_us(100);
00225         }
00226 }
00227 
00228 //  Rolling LED pattern with fade
00229 
00230 void  ritari_assa(void)
00231 {
00232 unsigned char i = 0;
00233 signed char act = 1, dir = 0;
00234 unsigned char disp[6] = {0, 0, 0, 0, 0, 0};
00235 unsigned char strength[6] = {32, 16, 8, 1, 0, 0};
00236 
00237         speed =eeprom_read_word(&user_speed); //Get default speed from EEPROM
00238 
00239         while(!pressed(KEY_MODE))
00240         {   
00241                 for(i=0;i<5;i++)
00242                         disp[5-i] = disp[4-i];
00243                 disp[0] = act;
00244                 for(i=0;i<5;i++)
00245                         LED[disp[5-i]] = strength[5-i];
00246                 if(dir == 0)
00247                 {
00248                         if(++act > 5)
00249                                 dir = -1;
00250                 }
00251                 else
00252                 {
00253                         if(--act < 0)
00254                                 dir = 0;
00255                 }
00256                 
00257                 if(pressed(KEY_A))      //Increase Speed at KEY_A
00258                 {
00259                         if (speed < 128)
00260                                 speed = (speed << 1);
00261                 }
00262                 _delay_us(100);
00263                 
00264                 if(pressed(KEY_B))              //Decrease Speed at KEY_B
00265                 {
00266                         if (speed > 4)
00267                                 speed = (speed >> 1);
00268                 }
00269                 _delay_us(100);
00270                 
00271                 for(i=0; i<speed; i++)
00272                         _delay_us(100);
00273         }
00274 }
00275 
00276 //  Blinking LED pattern with fade
00277 
00278 void  twinkle(void)
00279 {
00280 unsigned char i, j = 2;
00281 
00282         speed =eeprom_read_word(&user_speed);
00283         srand(TCNT1);                 // seed value for random number generator
00284         while(!pressed(KEY_MODE))
00285         {
00286                 for(i=0; i<12; i++)
00287                         LED[i] = (LED[i] >> 1);
00288                 if(--j == 0)
00289                 {
00290                         j = rand() % 11;
00291                         if(LED[j] == 0)
00292                                 LED[j] = 32;
00293                         j = (rand() >> 12) + 1;
00294                 }
00295         }
00296 }
00297 
00298 // Intialise Timer and Port values
00299 
00300 void  initialise(void)
00301 {
00302         TCCR1A = 0x00;                // no waveform generation, normal t/c
00303         TCCR1B = 0x01;                // no waveform generation, clk/1
00304         OCR1A = 0x00;
00305         OCR1B = 0x00;
00306         TIMSK1 = (1<< TOIE1);         // t/c overflow interrupt enable
00307         DDRA = 0x7f;                  // PA0...6 outputs
00308         DDRB = 0xcb;                  // PB0,1,3,6,7 outputs
00309         sei();
00310 }
00311 
00312 
00313 int  main( void )
00314 {
00315 unsigned char i;
00316 unsigned char mode = 0;
00317 
00318         initialise();
00319         while(1)
00320         {
00321                 for(i=0;i<12;i++)
00322                         LED[i] = 0;
00323                 while(pressed(KEY_MODE))
00324                 {
00325                         // wait for key to be released
00326                 }
00327                 switch(mode++)
00328                 {
00329                         case 0: 
00330                                         idle();
00331                                         break;
00332                         case 1: 
00333                                         torch();
00334                                         break;
00335                         case 2: 
00336                                         battery_gauge();
00337                                         break;
00338                         case 3: 
00339                                         dice_game();
00340                                         break;
00341                         case 4: 
00342                                         ritari_assa();
00343                                         break;
00344                         case 5: 
00345                                         twinkle();
00346                                         break;
00347                 }
00348                 if(mode > 5)
00349                         mode = 0;
00350         }
00351 }
00352 
00353 // FUNCTIONS
00354 
00355 //  Turn on a single LED. Called from ISR, only. LED layout:
00356 //  --------------------------
00357 //  10      09      08      07
00358 //  06  05  04  03  02  01  00
00359 //  09      10      07      08
00360 //  --------------------------
00361 
00362 void  setLED(unsigned char led)
00363 
00364 {
00365         switch(led)
00366         {
00367         case 0:         
00368                                 PORTA = PINA & 0xfe;  // xxxxxxx0
00369                     break;
00370                 case 1: 
00371                                 PORTA = PINA & 0xfd;  // xxxxxx0x
00372                 break;
00373         case 2: 
00374                                 PORTA = PINA & 0xfb;  // xxxxx0xx
00375                 break;
00376         case 3: 
00377                                 PORTA = PINA & 0xf7;  // xxxx0xxx
00378                 break;
00379         case 4: 
00380                                 PORTA = PINA & 0xef;  // xxx0xxxx
00381                 break;
00382         case 5: 
00383                                 PORTA = PINA & 0xdf;  // xx0xxxxx
00384                 break;
00385         case 6: 
00386                                 PORTA = PINA & 0xbf;  // x0xxxxxx
00387                 break;
00388         case 7: 
00389                                 PORTB = PINB & 0xfe;  // xxxxxxx0
00390                 break;
00391         case 8: 
00392                                 PORTB = PINB & 0xf7;  // xxxx0xxx
00393                 break;
00394         case 9: 
00395                                 PORTB = PINB & 0xbf;  // x0xxxxxx
00396                 break;
00397         case 10:
00398                                 PORTB = PINB & 0x7f;  // 0xxxxxxx
00399                 break;
00400         case 11:
00401                                 PORTB = PINB & 0xfd;  // xxxxxx0x
00402                 break;
00403         }
00404 }
00405 
00406 //  Turn off a single LED. Called from ISR, only.
00407 
00408 void  clearLED(unsigned char led)
00409 {
00410         switch(led)
00411         {
00412                 case 0:
00413                                 PORTA = PINA | 0x01;  // xxxxxxx1
00414                                 break;
00415         case 1: 
00416                                 PORTA = PINA | 0x02;  // xxxxxx1x
00417                 break;
00418         case 2: 
00419                                 PORTA = PINA | 0x04;  // xxxxx1xx
00420                 break;
00421         case 3: 
00422                                 PORTA = PINA | 0x08;  // xxxx1xxx
00423                 break;
00424         case 4: 
00425                                 PORTA = PINA | 0x10;  // xxx1xxxx
00426                 break;
00427         case 5: 
00428                                 PORTA = PINA | 0x20;  // xx1xxxxx
00429                 break;
00430         case 6: 
00431                                 PORTA = PINA | 0x40;  // x1xxxxxx
00432                 break;
00433         case 7: 
00434                                 PORTB = PINB | 0x01;  // xxxxxxx1
00435                 break;
00436         case 8: 
00437                                 PORTB = PINB | 0x08;  // xxxx1xxx
00438                 break;
00439         case 9: 
00440                                 PORTB = PINB | 0x40;  // x1xxxxxx
00441                 break;
00442         case 10:
00443                                 PORTB = PINB | 0x80;  // 1xxxxxxx
00444                 break;
00445         case 11:
00446                                 PORTB = PINB | 0x02;  // xxxxxx1x
00447                 break;
00448         }
00449 }
00450 
00451 
00452 // ISRs -- INTERRUPT SERVICE ROUTINES
00453 
00454 // Timer/counter overflow interrupt handler
00455 // Scan inputs and toggle LEDs according to intensity settings in LED[] array
00456 
00457 ISR(TIM1_OVF_vect)
00458 {
00459 unsigned char i;
00460 
00461         // scan switches, store results in buffer for debouncing
00462         keybuffer[keybuffer_index++] = ~PINB;   // switches are logically inverted
00463 
00464         if(keybuffer_index > 7)
00465         keybuffer_index = 0;
00466 
00467         if(led_pwm == 0)
00468         {
00469         for(i=0;i<12;i++)
00470         {
00471                         if(LED[i] > 0)
00472                         setLED(i);
00473                 else
00474                         clearLED(i);
00475                 }
00476         }
00477         else
00478         {
00479                 for(i=0;i<12;i++)
00480                 {
00481                         if(LED[i] == led_pwm)
00482                                 clearLED(i);
00483                 }
00484         }
00485 
00486         if(++led_pwm > 31)  
00487                 led_pwm = 0;
00488 }
00489 
@DOC_TITLE@
Generated on Thu Jun 11 18:28:03 2009 for AVR652: ATtiny43U Demonstration Kit by doxygen 1.5.8